﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Red.Controls.Utils;

namespace Red.Controls.Extensions
{
    /// <summary>
    /// Provides extended support for drag drop operation
    /// </summary>
    public static class TreeViewExtension
    {

        #region SelectOnRightMouseDown

        public static readonly DependencyProperty SelectOnRightMouseDownProperty =
            DependencyProperty.RegisterAttached( "SelectOnRightMouseDown",
                typeof( bool ),
                typeof( TreeViewExtension ),
                new PropertyMetadata( false, HandleSelectOnRightMouseDownChanged ) );

        public static bool GetSelectOnRightMouseDown( DependencyObject element )
        {
            return (bool)element.GetValue( SelectOnRightMouseDownProperty );
        }

        public static void SetSelectOnRightMouseDown( DependencyObject element, bool value )
        {
            element.SetValue( SelectOnRightMouseDownProperty, value );
        }

        private static void HandleSelectOnRightMouseDownChanged( DependencyObject obj, DependencyPropertyChangedEventArgs e )
        {
            FrameworkElement element = obj as FrameworkElement;
            if ( element == null ) throw new ArgumentException( "Invalid object type" );

            element.PreviewMouseRightButtonDown -= OnContainerPreviewRightButtonDown;
            if ( true.Equals( e.NewValue ) )
                element.PreviewMouseRightButtonDown += OnContainerPreviewRightButtonDown;
        }

        #endregion SelectOnRightMouseDown

        #region BringSelectedItemIntoView

        public static readonly DependencyProperty BringSelectedItemIntoViewProperty =
            DependencyProperty.RegisterAttached( "BringSelectedItemIntoView",
                typeof( bool ),
                typeof( TreeViewExtension ),
                new PropertyMetadata( false, HandleBringSelectedItemIntoViewChanged ) );

        public static bool GetBringSelectedItemIntoView( DependencyObject element )
        {
            return (bool)element.GetValue( BringSelectedItemIntoViewProperty );
        }

        public static void SetBringSelectedItemIntoView( DependencyObject element, bool value )
        {
            element.SetValue( BringSelectedItemIntoViewProperty, value );
        }

        private static void HandleBringSelectedItemIntoViewChanged( DependencyObject obj, DependencyPropertyChangedEventArgs e )
        {
            TreeView tree = obj as TreeView;
            if ( tree == null ) throw new ArgumentException( "Invalid object type" );

            var handler = new RoutedEventHandler( OnTreeItemSelected );

            tree.RemoveHandler( TreeViewItem.SelectedEvent, handler );
            if ( true.Equals( e.NewValue ) )
                tree.AddHandler( TreeViewItem.SelectedEvent, handler );
        }

        #endregion BringSelectedItemIntoView

        #region Event handlers

        private static void OnContainerPreviewRightButtonDown( object sender, MouseButtonEventArgs e )
        {
            TreeViewItem item = Helpers.FindVisualAncestorOfType<TreeViewItem>( e.OriginalSource );

            if ( item != null )
            {
                item.IsSelected = true;
            }
        }

        private static void OnTreeItemSelected( object sender, RoutedEventArgs e )
        {
            var item = e.OriginalSource as TreeViewItem;
            item.BringIntoView();
        }

        #endregion Event handlers
    }
}